﻿using CoreShop.Library;
using CoreShop.Model;
using CoreShop.Model.FromBody;
using CoreShop.Model.UI;
using CoreShop.PrintService;
using CoreShop.Services;
using FastMember;
using gregn6Lib;
using IWshRuntimeLibrary;
using Newtonsoft.Json;
using NPOI.HSSF.Record;
using NPOI.SS.Formula.Functions;
using NPOI.Util;
using SqlSugar;
using SqlSugar.Extensions;
using Sunny.UI;
using Sunny.UI.Win32;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Security.Policy;
using System.Windows.Forms;
using static CoreShop.Library.GlobalEnumVars;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;

namespace CoreShop.App
{
    public partial class frmPrintTemplatePool : UIForm
    {
        int typeId = 0;
        int templateTypeId = 0;//模板库ID
        private List<corecmsprintbilltemplate> billtemplateList = null;
        private Axgregn6Lib.AxGRPrintViewer axGRPrintViewer1 = new Axgregn6Lib.AxGRPrintViewer();
        private GridppReport Report = new GridppReport();
        protected GridppReport SubFoodType = new GridppReport();//商品分类
        protected GridppReport SubFoodDepart = new GridppReport();//商品部门
        protected GridppReport SubPayment = new GridppReport();//合计付款方式
        protected GridppReport SubPresent = new GridppReport();//合计付款方式
        private corecmsprintbilltemplate printbilltemplate = null;

        public frmPrintTemplatePool(corecmsprintbilltemplate _printbilltemplate)
        {
            printbilltemplate = _printbilltemplate;
            InitializeComponent();
            Fonts.Add(1, new Font("宋体", 12));
            Fonts.Add(2, new Font("宋体", 24));
            Fonts.Add(3, new Font("宋体", 36));
            this.axGRPrintViewer1 = new Axgregn6Lib.AxGRPrintViewer();
            ((System.ComponentModel.ISupportInitialize)(this.axGRPrintViewer1)).BeginInit();
            this.axGRPrintViewer1.Dock = System.Windows.Forms.DockStyle.Fill;
            this.axGRPrintViewer1.Enabled = true;
            this.axGRPrintViewer1.Location = new System.Drawing.Point(0, 0);
            this.axGRPrintViewer1.Name = "axGRPrintViewer1";
            this.axGRPrintViewer1.Size = new System.Drawing.Size(712, 470);
            this.axGRPrintViewer1.TabIndex = 1;
            this.pnlPrintViewer.Controls.Add(this.axGRPrintViewer1);
            ((System.ComponentModel.ISupportInitialize)(this.axGRPrintViewer1)).EndInit();
        }

        #region 报表渲染数据

        private void ReportFetchRecord()
        {
            try
            {                
                Report.DetailGrid.Recordset.Empty();
                for (int i = 0; i < 2; i++)
                {
                    Report.DetailGrid.Recordset.Append();
                    foreach (IGRField fld in Report.DetailGrid.Recordset.Fields)
                    {
                        fld.Value = fld.Tag;
                    }
                    Report.DetailGrid.Recordset.Post();
                }
            }
            catch { }
        }
        private void ReportFetchRecord_SubFoodType()
        {
            //获取子报表的内部报表对象  
            try
            {
                SubFoodType.DetailGrid.Recordset.Empty();
                for (int i = 0; i < 1; i++)
                {
                    SubFoodType.DetailGrid.Recordset.Append();
                    foreach (IGRField fld in SubFoodType.DetailGrid.Recordset.Fields)
                    {
                        fld.Value = fld.Tag;
                    }
                    SubFoodType.DetailGrid.Recordset.Post();
                }
            }
            catch { }            
        }

        private void ReportFetchRecord_SubFoodDepart()
        {
            //获取子报表的内部报表对象  
            try
            {
                SubFoodDepart.DetailGrid.Recordset.Empty();
                for (int i = 0; i < 2; i++)
                {
                    SubFoodDepart.DetailGrid.Recordset.Append();
                    foreach (IGRField fld in SubFoodDepart.DetailGrid.Recordset.Fields)
                    {
                        fld.Value = fld.Tag;
                    }
                    SubFoodDepart.DetailGrid.Recordset.Post();
                }
            }
            catch { }            
        }

        //在C#中一次填入一条记录不能成功，只能使用一次将记录全部填充完的方式
        private void ReportFetchRecord_SubPresent()
        {
            //获取子报表的内部报表对象  
            try
            {
                SubPresent.DetailGrid.Recordset.Empty();
                for (int i = 0; i < 1; i++)
                {
                    SubPresent.DetailGrid.Recordset.Append();
                    foreach (IGRField fld in SubPresent.DetailGrid.Recordset.Fields)
                    {
                        fld.Value = fld.Tag;
                    }
                    SubPresent.DetailGrid.Recordset.Post();
                }
            }
            catch { }            
        }

        //在C#中一次填入一条记录不能成功，只能使用一次将记录全部填充完的方式
        private void ReportFetchRecord_SubRptPay()
        {
            //获取子报表的内部报表对象  
            try
            {
                SubPayment.DetailGrid.Recordset.Empty();
                for (int i = 0; i < 1; i++)
                {
                    SubPayment.DetailGrid.Recordset.Append();
                    foreach (IGRField fld in SubPayment.DetailGrid.Recordset.Fields)
                    {
                        fld.Value = fld.Tag;
                    }
                    SubPayment.DetailGrid.Recordset.Post();
                }
            }
            catch { }            
        }


        #endregion

        /// <summary>
        /// 加载小票类型
        /// </summary>
        private void LoadPrintScheme()
        {
            var where = Expressionable.Create<corecmsprintbilltype>();
            where = where.And(p => p.id > 0);

            //如果不启用厨房打印，不显示厨房打印方案名称
            if (!AppConstVars.systemsetup.isKitchen)
                where = where.And(p => p.tagId != (int)GlobalEnumVars.PrintbillTypeTag.Kitchen);
            
            if (printbilltemplate != null)
                where = where.And(p => p.id == printbilltemplate.billtypeId);

            List<corecmsprintbilltype> lstSource = new corecmsprintbilltypeServices().AsQueryable()
                .Where(where.ToExpression()).OrderBy(p => p.tagId).ToList();

            tvTemplate.Nodes.Clear();
            TreeNode treeNode = new TreeNode("全部票据");
            treeNode.Tag = "0";
            tvTemplate.Nodes.Add(treeNode);
            foreach (var item in lstSource)
            {
                TreeNode treeNode10 = new TreeNode(item.name);
                treeNode10.Tag = item.id.ToString();
                treeNode.Nodes.Add(treeNode10);
            }
            tvTemplate.Nodes[0].Expand();
        }

        private void FDishPinterSetup_Shown(object sender, System.EventArgs e)
        {

        }

        private void LoadReport(corecmsprintbilltemplate billtemplate)
        {
            try
            {
                if (string.IsNullOrEmpty(billtemplate.reportData)) return;
                axGRPrintViewer1.Stop();
                Report.LoadFromStr(billtemplate.reportData);
                Report.FetchRecord += new _IGridppReportEvents_FetchRecordEventHandler(ReportFetchRecord);
                try
                {
                    SubFoodType = Report.ControlByName("SubFoodType").AsSubReport.Report;
                    SubFoodType.FetchRecord += new _IGridppReportEvents_FetchRecordEventHandler(ReportFetchRecord_SubFoodType);
                }
                catch { }
                try
                {
                    SubFoodDepart = Report.ControlByName("SubFoodDepart").AsSubReport.Report;
                    SubFoodDepart.FetchRecord += new _IGridppReportEvents_FetchRecordEventHandler(ReportFetchRecord_SubFoodDepart);
                }
                catch { }
                try
                {
                    SubFoodDepart = Report.ControlByName("SubFoodDepart").AsSubReport.Report;
                    SubFoodDepart.FetchRecord += new _IGridppReportEvents_FetchRecordEventHandler(ReportFetchRecord_SubFoodDepart);
                }
                catch { }
                try
                {
                    SubPresent = Report.ControlByName("SubPresent").AsSubReport.Report;
                    SubPresent.FetchRecord += new _IGridppReportEvents_FetchRecordEventHandler(ReportFetchRecord_SubPresent);
                }
                catch { }

                try
                {
                    SubPayment = Report.ControlByName("SubPayment").AsSubReport.Report;
                    SubPayment.FetchRecord += new _IGridppReportEvents_FetchRecordEventHandler(ReportFetchRecord_SubRptPay);
                }
                catch { }
                axGRPrintViewer1.Report = Report;
                axGRPrintViewer1.Start();
            }
            catch { }
        }
    

        /// <summary>
        /// 加载模板类型
        /// </summary>
        private void LoadTemplateTypeList()
        {
            string msg = "";            
            List<corecmsprintbilltemplatetype> templatetypes = new ApiRemoteServices().GetBillTemplateTypeList(ref msg);
            if (templatetypes != null)
            {
                tvTemplateType.Nodes.Clear();
                TreeNode treeNode = new TreeNode("模板列表");
                treeNode.Tag = "0";
                tvTemplateType.Nodes.Add(treeNode);
                foreach (var item in templatetypes)
                {
                    TreeNode treeNode10 = new TreeNode(item.name);
                    treeNode10.Tag = item.id.ToString();
                    treeNode.Nodes.Add(treeNode10);
                }
                tvTemplateType.Nodes[0].Expand();
            }
            else UIMessageBox.Show(msg);
        }

        private void LoadComboData()
        {
            #region 纸张宽度
            paperType.Enabled = false;
            this.paperType.Items.Clear();
            var paperTypeList = EnumHelper.EnumToList<GlobalEnumVars.paperType>();
            paperType.DataSource = paperTypeList;
            paperType.DisplayMember = "description";
            paperType.ValueMember = "value";
            this.paperType.SelectedValue =  (int)GlobalEnumVars.paperType.eighty;
            paperType.Enabled = true;
            #endregion
        }

        private void frmPrintTemplate_Load(object sender, System.EventArgs e)
        {
            tbcPrintViewer.TabVisible = false;
            lblMsg.Text = "";
            LoadComboData();
            GetBillTemplateList();
            LoadTemplateTypeList();            
            LoadPrintScheme();            
            tvTemplate.ExpandAll();
        }

        private void btnExit_Click(object sender, System.EventArgs e)
        {
            this.Close();
        }

        private void tvBilltype_AfterSelect(object sender, TreeViewEventArgs e)
        {
            typeId = CommFunc.ConvertToInt32(e.Node.Tag);
            GetTemplatDetail(typeId);
        }

        #region IP打印机渲染
        private PrintService.Menu menu;
        private object MenuObj;
        private object DataObj;
        private object DataTotalObj;
        private readonly Dictionary<int, Font> Fonts = new Dictionary<int, Font>();

        private void Image_Paint(object sender, PaintEventArgs e)
        {
            int border = 4;
            int top = 4;
            if (menu == null) return;

            top = DrawLines(e.Graphics, menu.Header, border, top);
            top = DrawData(e.Graphics, menu.Center, border, top);
            DrawLines(e.Graphics, menu.Footer, border, top);
        }

        private void UpdateShow(corecmsprintbilltemplate billtemplate)
        {
            menu = Json.Deserialize<PrintService.Menu>(billtemplate.content);
            if (billtemplate.paperType == (int)GlobalEnumVars.paperType.fifty_eight)
            {
                this.Image.Width = 280;
                menu.PageSize = PageSize.W58;
            }
            else if (billtemplate.paperType == (int)GlobalEnumVars.paperType.seventy_five)
            {
                this.Image.Width = 341;
                menu.PageSize = PageSize.W76;
            }
            else
            {
                menu.PageSize = PageSize.W80;
                this.Image.Width = 356;
            }

            LoadMemuObjData();
            Image.Invalidate();
        }

        private void LoadMemuObjData()
        {
            int count = 0;
            var PrintSrv = new PrintServices();
            var taskdetails = new corecmsprinttaskdetailServices().QueryPageAsync(ref count, 1, 2, -1, "");
            if (taskdetails.Count > 0)
            {
                var taskdetail = taskdetails.First();
                if (taskdetail.taskTitle.IsNullOrEmpty()) taskdetail.taskTitle = "微辣";
                if (taskdetail.feedTitle.IsNullOrEmpty()) taskdetail.feedTitle = "加鸡蛋";
                if (taskdetail.detailRemark.IsNullOrEmpty()) taskdetail.detailRemark = "加急";
                var obj = PrintSrv.GetMenuObject(taskdetail);
                MenuObj = obj;
                List<MenuObject> list = new List<MenuObject> { obj };
                DataObj = list;
            }
        }

        private int DrawLine(Graphics g, int border, int top)
        {
            try
            {
                SizeF sf = g.MeasureString("-", Fonts[1]);
                g.DrawString("-".Repeat(menu.PageSize.CharCount()), Fonts[1], Color.Black, border, top);
                return top + (int)sf.Height;
            }
            catch { }
            return 0;
        }

        private int DrawData(Graphics g, List<MenuLine> lines, int border, int top)
        {
            try
            {
                TypeAccessor accessors = null;
                List<string> members = new List<string>();
                if (DataObj != null)
                {
                    accessors = TypeAccessor.Create(typeof(MenuObject));
                    var m = accessors.GetMembers();
                    foreach (var t in m)
                    {
                        members.Add(t.Name);
                    }
                }

                foreach (MenuLine line in lines)
                {
                    int width = Image.Width;
                    int totalWeight = line.GetTotalWeight();
                    int left = border;
                    Font font = new Font("宋体", line.FontSize * 12);
                    SizeF sf = g.MeasureString("item.Text", font);

                    if (!(DataObj is IList))
                    {
                        for (int i = 1; i <= 3; i++)
                        {
                            string text = "*".Repeat(i);
                            left = border;
                            foreach (var item in line.Items)
                            {
                                int weight = (width - border * 2 - (line.Items.Count - 1) * border) * item.Weight / totalWeight;
                                SizeF sf1 = g.MeasureString(text, font);
                                if (item.DataAlign == eTextAlignMode.Left)
                                    g.DrawString(text, font, Brushes.Black, left, top);
                                if (item.DataAlign == eTextAlignMode.Middle)
                                    g.DrawString(text, font, Brushes.Black, left + (weight - sf1.Width) / 2, top);
                                if (item.DataAlign == eTextAlignMode.Right)
                                    g.DrawString(text, font, Brushes.Black, left + weight - sf1.Width, top);

                                left += weight + border;
                            }

                            top += (int)sf.Height;
                        }
                    }
                    else
                    {
                        IList list = DataObj as IList;
                        foreach (object o in list)
                        {
                            string text = "";
                            left = border;
                            int idx = 0;
                            foreach (var item in line.Items)
                            {
                                if (members.IndexOf(item.DataPropertyName) >= 0)
                                    text = accessors[o, item.DataPropertyName].ToString();
                                int weight = (width - border * 2 - (line.Items.Count - 1) * border) * item.Weight / totalWeight;
                                SizeF sf1 = g.MeasureString(text, font);
                                if (item.DataAlign == eTextAlignMode.Left)
                                    g.DrawString(text, font, Brushes.Black, left, top);
                                if (item.DataAlign == eTextAlignMode.Middle)
                                    g.DrawString(text, font, Brushes.Black, left + (weight - sf1.Width) / 2, top);
                                if (item.DataAlign == eTextAlignMode.Right)
                                    g.DrawString(text, font, Brushes.Black, left + weight - sf1.Width, top);

                                if (menu.Multi && idx == 0) top += (int)sf.Height;
                                idx++;
                                left += weight + border;
                            }

                            top += (int)sf.Height;
                        }

                        if (DataTotalObj != null)
                        {
                            left = border;
                            top = DrawLine(g, border, top);
                            foreach (var item in line.Items)
                            {
                                string text = "";
                                if (members.IndexOf(item.DataPropertyName) >= 0)
                                    text = accessors[DataTotalObj, item.DataPropertyName].ToString();

                                int weight = (width - border * 2 - (line.Items.Count - 1) * border) * item.Weight / totalWeight;
                                SizeF sf1 = g.MeasureString(text, font);
                                if (item.DataAlign == eTextAlignMode.Left)
                                    g.DrawString(text, font, Brushes.Black, left, top);
                                if (item.DataAlign == eTextAlignMode.Middle)
                                    g.DrawString(text, font, Brushes.Black, left + (weight - sf1.Width) / 2, top);
                                if (item.DataAlign == eTextAlignMode.Right)
                                    g.DrawString(text, font, Brushes.Black, left + weight - sf1.Width, top);

                                left += weight + border;
                            }

                            top += (int)sf.Height;
                        }
                    }
                }
                return top;
            }
            catch { }
            return 0;
        }

        private int DrawLines(Graphics g, List<MenuLine> lines, int border, int top)
        {
            int width = Image.Width;
            try
            {
                TypeAccessor accessors = null;
                List<string> members = new List<string>();
                if (MenuObj != null)
                {
                    accessors = TypeAccessor.Create(typeof(MenuObject));
                    var m = accessors.GetMembers();
                    foreach (var t in m)
                    {
                        members.Add(t.Name);
                    }
                }

                foreach (MenuLine line in lines)
                {
                    if (line.IsLine)
                    {
                        top = DrawLine(g, border, top);
                    }
                    else
                    {
                        int totalWeight = line.GetTotalWeight();
                        int left = border;
                        Font font = new Font("宋体", line.FontSize * 12);
                        SizeF sf = g.MeasureString("item.Text", font);

                        foreach (var item in line.Items)
                        {
                            int weight = (width - border * 2 - (line.Items.Count - 1) * border) * item.Weight / totalWeight;
                            SizeF sf1 = g.MeasureString(item.Text, font);

                            if (item.DataPropertyName.IsNullOrEmpty())
                            {
                                if (item.TextAlign == eTextAlignMode.Left)
                                    g.DrawString(item.Text, font, Brushes.Black, left, top);
                                if (item.TextAlign == eTextAlignMode.Middle)
                                    g.DrawString(item.Text, font, Brushes.Black, left + (weight - sf1.Width) / 2, top);
                                if (item.TextAlign == eTextAlignMode.Right)
                                    g.DrawString(item.Text, font, Brushes.Black, left + weight - sf1.Width, top);
                            }
                            else
                            {
                                string text = "XX";

                                if (accessors != null && members.IndexOf(item.DataPropertyName) >= 0)
                                    text = accessors[MenuObj, item.DataPropertyName].ToString();

                                SizeF sf2 = g.MeasureString(text, font);
                                if (item.TextAlign == eTextAlignMode.Left || item.TextAlign == eTextAlignMode.Middle)
                                {
                                    g.DrawString(item.Text, font, Brushes.Black, left, top);

                                    if (item.DataAlign == eTextAlignMode.Left)
                                        g.DrawString(text, font, Brushes.Black, left + sf1.Width, top);
                                    if (item.DataAlign == eTextAlignMode.Middle)
                                        g.DrawString(text, font, Brushes.Black, left + sf1.Width + ((weight - sf1.Width) - sf2.Width) / 2, top);
                                    if (item.DataAlign == eTextAlignMode.Right)
                                        g.DrawString(text, font, Brushes.Black, left + weight - sf2.Width, top);
                                }

                                if (item.TextAlign == eTextAlignMode.Right)
                                {
                                    g.DrawString(item.Text, font, Brushes.Black, left + weight - sf1.Width - sf2.Width, top);
                                    g.DrawString(text, font, Brushes.Black, left + weight - sf2.Width, top);
                                }
                            }

                            left += weight + border;
                        }

                        top += (int)sf.Height;
                        font.Dispose();
                    }
                }

                return top;
            }
            catch { }
            return 0;
        }


        #endregion

        private void btnEditPrintBilltype_Click(object sender, EventArgs e)
        {
            if (typeId < 1) { UIMessageBox.Show("请选择需要修改的数据", "系统提示", UIStyle.Black, UIMessageBoxButtons.OK); return; }
            corecmsprintbilltemplate template = new corecmsprintbilltemplateServices().SelectById(typeId);
            frmPrintTemplateInfo frm = new frmPrintTemplateInfo(template);
            frm.ShowDialog();
            frm.Dispose();
        }

        private string GetMenuItemName(long orderingId)
        {
            return "uiMenuItem_" + orderingId.ToString();
        }

        /// <summary>
        /// 加载模板
        /// </summary>
        private void GetTemplatDetail(int typeId)
        {
            //查询所有打印格式模板
            if (billtemplateList == null) return;
            var templates = billtemplateList.OrderBy(p => p.billtypeId);
            if (typeId > 0) templates = billtemplateList.Where(p=>p.billtypeId == typeId).ToList().OrderBy(p => p.billtypeId);
            laySchemeDetail.Visible = false;
            laySchemeDetail.Clear();
            foreach (var info in templates)
            {
                if (info.billtypeId == (int)GlobalEnumVars.PrintbillType.Label)
                    info.paperType = (int)GlobalEnumVars.paperType.custom;//标签纸张大小显示为显示自定义
                UIDishPrintbillTemplatePool item = new UIDishPrintbillTemplatePool(info);
                item.Tag = "2";
                item.Name = GetMenuItemName(info.id);
                item.TableClick += Item_TableClick;
                laySchemeDetail.Add(item);
            }
            laySchemeDetail.Visible = true;
        }

        private void Item_TableClick(object sender, System.EventArgs e)
        {
            var item = (UIDishPrintbillTemplatePool)sender;
            var template = item.Info;

            var billtype = new corecmsprintbilltypeServices().GetById(template.billtypeId);

            if (billtype.tagId == (int)GlobalEnumVars.PrintbillTypeTag.Kitchen)
            {
                tbcPrintViewer.SelectedIndex = 1;
                UpdateShow(template);
            }
            else
            {
                tbcPrintViewer.SelectedIndex = 0;
                LoadReport(template);
            }                      
        }

        private void GetBillTemplateList()
        {
            int mPaperType = CommFunc.ConvertToInt32(paperType.SelectedValue);
            string msg = "";
            //billtemplateList = new PosRemoteServices(AppConstVars.sUrl).GetBillTemplateList(AppConstVars.sysUser.ccessToken
            //    , templateTypeId, mPaperType, printbilltemplate, ref msg);
            //if (billtemplateList != null)
            //{

            //}
            //else UIMessageBox.Show(msg);
        }

        private void tvTemplateType_AfterSelect(object sender, TreeViewEventArgs e)
        {
            templateTypeId = CommFunc.ConvertToInt32(e.Node.Tag);
            GetBillTemplateList();
            GetTemplatDetail(typeId);
        }

        private void paperType_SelectedValueChanged(object sender, EventArgs e)
        {
            if (paperType.Enabled)
            {
                GetBillTemplateList();
                GetTemplatDetail(typeId);
            }
        }
        private void btnAddbilltemplate_Click(object sender, EventArgs e)
        {
            List<corecmsprintbilltemplate> billtemplateNew = new List<corecmsprintbilltemplate>();
            foreach (var item in billtemplateList)
            {
                var mControl = laySchemeDetail.Get(GetMenuItemName(item.id));
                if (mControl == null) continue;
                var sTemplatePool = (UIDishPrintbillTemplatePool)mControl;
                if (!sTemplatePool.Checked) continue;
                var info = sTemplatePool.Info;
                if (printbilltemplate != null)
                {
                    printbilltemplate.content = info.content;
                    printbilltemplate.reportData = info.reportData;
                    new corecmsprintbilltemplateServices().UpdateAsync(printbilltemplate);
                }
                else
                {
                    info.id = 0;
                    billtemplateNew.Add(info);
                }
            }
            if ((billtemplateNew != null) && (billtemplateNew.Count > 0))
            {
                var bl  = new corecmsprintbilltemplateServices().InsertRange(billtemplateNew);
                if (!bl)
                {
                    UIMessageBox.Show("导入模板失败。", "系统提示", UIStyle.Black, UIMessageBoxButtons.OK);
                    return;
                }
            }
            this.DialogResult = System.Windows.Forms.DialogResult.OK;
        }

        private void uiCheckBox1_Click(object sender, EventArgs e)
        {
            foreach (var item in billtemplateList)
            {
                var mControl = laySchemeDetail.Get(GetMenuItemName(item.id));
                if (mControl == null) continue;
                var sTemplatePool = (UIDishPrintbillTemplatePool)mControl;
                sTemplatePool.Checked = uiCheckBox1.Checked;
                sTemplatePool.Refresh();
            }
        }
    }
}
